{
 "cells": [
  {
   "cell_type": "markdown",
   "source": [
    "## CNN模型"
   ],
   "metadata": {
    "collapsed": false
   },
   "id": "6422cb83f69c20b5"
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "initial_id",
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import pickle\n",
    "import os\n",
    "import matplotlib.pyplot as plt\n",
    "import seaborn as sns\n",
    "from sklearn.metrics import accuracy_score, precision_recall_fscore_support, confusion_matrix, classification_report\n",
    "# 数据集路径\n",
    "data_dir = r'D:\\Machine_learning\\jiqixuexi\\cifar-10-python\\cifar-10-batches-py'"
   ]
  },
  {
   "cell_type": "markdown",
   "source": [
    "### 加载数据及数据预处理"
   ],
   "metadata": {
    "collapsed": false
   },
   "id": "b8d176ff761f70d6"
  },
  {
   "cell_type": "code",
   "outputs": [],
   "source": [
    "# 加载CIFAR-10数据集\n",
    "def load_cifar10_data(data_dir):\n",
    "    # 加载训练数据\n",
    "    train_data = []\n",
    "    train_labels = []\n",
    "    for i in range(1, 6):\n",
    "        batch_path = os.path.join(data_dir, f'data_batch_{i}')\n",
    "        with open(batch_path, 'rb') as file:\n",
    "            batch = pickle.load(file, encoding='latin1')\n",
    "            train_data.append(batch['data'])\n",
    "            train_labels.extend(batch['labels'])\n",
    "    train_data = np.array(train_data).reshape(50000, 3, 32, 32).transpose(0, 2, 3, 1)\n",
    "    train_labels = np.array(train_labels)\n",
    "\n",
    "    # 加载测试数据\n",
    "    test_batch_path = os.path.join(data_dir, 'test_batch')\n",
    "    with open(test_batch_path, 'rb') as file:\n",
    "        test_batch = pickle.load(file, encoding='latin1')\n",
    "    test_data = test_batch['data'].reshape(10000, 3, 32, 32).transpose(0, 2, 3, 1)\n",
    "    test_labels = np.array(test_batch['labels'])\n",
    "\n",
    "    return (train_data, train_labels), (test_data, test_labels)\n",
    "\n",
    "# 调用函数加载数据\n",
    "(train_data, train_labels), (test_data, test_labels) = load_cifar10_data(data_dir)\n",
    "\n",
    "# 数据预处理\n",
    "train_data = train_data.astype('float32') / 255.0\n",
    "test_data = test_data.astype('float32') / 255.0\n"
   ],
   "metadata": {
    "collapsed": false
   },
   "id": "d6156cc6e484b605"
  },
  {
   "cell_type": "markdown",
   "source": [
    "### 模型训练与评估"
   ],
   "metadata": {
    "collapsed": false
   },
   "id": "b7527d4a07530473"
  },
  {
   "cell_type": "code",
   "outputs": [],
   "source": [
    "# 自主实现CNN模型\n",
    "class SimplifiedCNN:\n",
    "    def __init__(self):\n",
    "        # 初始化模型参数\n",
    "        self.conv1_weights = np.random.randn(32, 3, 3, 3)  \n",
    "        self.conv1_bias = np.zeros(32)\n",
    "        self.fc_weights = np.random.randn(32 * 16 * 16, 10)  \n",
    "        self.fc_bias = np.zeros(10)\n",
    "\n",
    "    def convolution(self, input_data, weights, bias):\n",
    "        batch_size, height, width, channels = input_data.shape\n",
    "        filter_size = weights.shape[0]\n",
    "        output_channels = weights.shape[3]\n",
    "        output = np.zeros((batch_size, height - filter_size + 1, width - filter_size + 1, output_channels))\n",
    "        for b in range(batch_size):\n",
    "            for c in range(output_channels):\n",
    "                for i in range(height - filter_size + 1):\n",
    "                    for j in range(width - filter_size + 1):\n",
    "                        output[b, i, j, c] = np.sum(input_data[b, i:i+filter_size, j:j+filter_size, :] * weights[:, :, :, c]) + bias[c]\n",
    "        return output\n",
    "\n",
    "    def max_pooling(self, input_data, pool_size):\n",
    "        batch_size, height, width, channels = input_data.shape\n",
    "        output_height = height // pool_size\n",
    "        output_width = width // pool_size\n",
    "        output = np.zeros((batch_size, output_height, output_width, channels))\n",
    "        for b in range(batch_size):\n",
    "            for c in range(channels):\n",
    "                for i in range(output_height):\n",
    "                    for j in range(output_width):\n",
    "                        output[b, i, j, c] = np.max(input_data[b, i*pool_size:(i+1)*pool_size, j*pool_size:(j+1)*pool_size, c])\n",
    "        return output\n",
    "\n",
    "    def forward(self, input_data):\n",
    "        # 前向传播\n",
    "        conv1 = self.convolution(input_data, self.conv1_weights, self.conv1_bias)\n",
    "        relu1 = np.maximum(conv1, 0)\n",
    "        pool1 = self.max_pooling(relu1, 2)\n",
    "        flatten = pool1.reshape(pool1.shape[0], -1)\n",
    "        logits = np.dot(flatten, self.fc_weights) + self.fc_bias\n",
    "        return logits\n",
    "\n",
    "    def compute_loss(self, logits, labels):\n",
    "        # 计算损失（交叉熵损失）\n",
    "        num_samples = logits.shape[0]\n",
    "        one_hot_labels = np.zeros_like(logits)\n",
    "        one_hot_labels[np.arange(num_samples), labels] = 1\n",
    "        loss = -np.sum(one_hot_labels * np.log(np.clip(logits, 1e-8, 1.0))) / num_samples\n",
    "        return loss\n",
    "\n",
    "    def train(self, train_data, train_labels,epochs=10, batch_size=32):\n",
    "        for epoch in range(epochs):\n",
    "            for i in range(0, len(train_data), batch_size):\n",
    "                batch_data = train_data[i:i+batch_size]\n",
    "                batch_labels = train_labels[i:i+batch_size]\n",
    "                logits = self.forward(batch_data)\n",
    "                loss = self.compute_loss(logits, batch_labels)\n",
    "                print(f'Epoch {epoch+1}, Batch {i//batch_size+1}, Loss: {loss}')\n",
    "\n",
    "    def evaluate(self, test_data, test_labels):\n",
    "        logits = self.forward(test_data)\n",
    "        predicted_labels = np.argmax(logits, axis=1)\n",
    "        accuracy = np.mean(predicted_labels == test_labels)\n",
    "        return predicted_labels, accuracy\n",
    "\n",
    "# 初始化模型\n",
    "model = SimplifiedCNN()\n",
    "\n",
    "# 训练模型\n",
    "model.train(train_data, train_labels, epochs=10, batch_size=64)\n",
    "\n",
    "# 评估模型\n",
    "predicted_labels, accuracy = model.evaluate(test_data, test_labels)\n",
    "print(f\"测试准确率: {accuracy:.4f}\")"
   ],
   "metadata": {
    "collapsed": false
   },
   "id": "199c25b883546fd0"
  },
  {
   "cell_type": "code",
   "outputs": [],
   "source": [
    "# 计算评估指标\n",
    "accuracy = accuracy_score(test_labels, predicted_labels)\n",
    "precision, recall, f1, _ = precision_recall_fscore_support(test_labels, predicted_labels, average='weighted')\n",
    "conf_matrix = confusion_matrix(test_labels, predicted_labels)\n",
    "class_report = classification_report(test_labels, predicted_labels)\n",
    "\n",
    "# 输出结果\n",
    "print(\"Accuracy:\", accuracy)\n",
    "print(\"Precision:\", precision)\n",
    "print(\"Recall:\", recall)\n",
    "print(\"F1-score:\", f1)\n",
    "print(\"Confusion Matrix:\\n\", conf_matrix)\n",
    "print(\"Classification Report:\\n\", class_report)"
   ],
   "metadata": {
    "collapsed": false
   },
   "id": "e0391913f62f13eb"
  },
  {
   "cell_type": "markdown",
   "source": [
    "### 热力图展示混淆矩阵"
   ],
   "metadata": {
    "collapsed": false
   },
   "id": "fcd4a82f7e980d76"
  },
  {
   "cell_type": "code",
   "outputs": [],
   "source": [
    "# 绘制混淆矩阵热力图\n",
    "plt.figure(figsize=(12, 8))\n",
    "sns.heatmap(conf_matrix, annot=True, fmt='d', cmap='Blues')\n",
    "plt.title(\"CNN - Confusion Matrix (CIFAR-10)\")\n",
    "plt.xlabel(\"Predicted Label\")\n",
    "plt.ylabel(\"True Label\")\n",
    "plt.show()"
   ],
   "metadata": {
    "collapsed": false
   },
   "id": "e00b074cc3cf7c42"
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
